package com.ly.heart.service.king;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.common.utils.spring.SpringUtils;
import com.ly.heart.domain.KingInventoryEntity;
import com.ly.heart.domain.KingInventoryMaterialDetailEntity;
import com.ly.heart.domain.KingInventoryMaterialEntity;
import com.ly.heart.domain.KingOrgEntity;
import com.ly.heart.domain.king.BaseChildBo;
import com.ly.heart.domain.king.inventory.FInStockEntryBo;
import com.ly.heart.domain.king.inventory.FInStockFinBo;
import com.ly.heart.domain.king.inventory.KingInventoryBo;
import com.ly.heart.domain.king.order.*;
import com.ly.heart.domain.request.KingBaseSingleRequest;
import com.ly.heart.domain.response.KingBaseResponse;
import com.ly.heart.domain.response.KingBaseResponseSuccessEntity;
import com.ly.heart.service.IKingInventoryService;
import com.ly.heart.service.IKingOrgService;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.heart.util.KingCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 采购入库单推送Service
 */
@Component
@Slf4j
public class KingInventoryPushService {

    private final SimpleDateFormat dateFormat = new SimpleDateFormat ( "yyyy-MM-dd" );

    @Resource
    private IKingInventoryService kingInventoryService;
    @Resource
    private IKingOrgService iKingOrgService;

    /**
     * 公用金蝶推送方法
     * 合并保存，提交，审核三步
     * @param kingInventoryId
     */
    public void push (String kingInventoryId) {
        KingOrgEntity orgEntity = iKingOrgService.getOne ( new LambdaQueryWrapper<KingOrgEntity> ().eq ( KingOrgEntity :: getOrgId, CurrentUserUtil.getCompanyId () ).eq ( KingOrgEntity :: getIsDisabled, false ) );
        if ( orgEntity == null ) {
            throw new CustomException ( "请先至系统管理中配置金蝶账套！" );
        }
        IdentifyInfo identifyInfo = KingCommonUtil.getIdentifyInfo ( orgEntity );
        KingInventoryEntity kingInventory = kingInventoryService.selectKingInventoryEntityById ( kingInventoryId );
        if ( Objects.isNull ( kingInventory ) ) {
            throw new CustomException ( "采购入库单不存在！" );
        }
        if ( kingInventory.getIsSend () == KingConstUtil.KING_DATA_IS_SEND_YES ) {
            throw new CustomException ( "该单据已推送金蝶,无需重复推送！" );
        }
        try {
            K3CloudApi client = new K3CloudApi ( identifyInfo );
            save ( kingInventory, client );
            submit ( kingInventory.getDocCode (), client );
            audit ( kingInventory.getDocCode (), client );
            updateSendSuccess ( kingInventoryId );
            //调用即时库存更新
            kingInventoryService.approvedSaleKingInventory ( kingInventory );
        } catch ( Exception e ) {
            e.printStackTrace ();
            throw new CustomException ( "推送采购入库单失败！" );
        }
    }

    /**
     * 修改推送状态
     * @param kingInventoryId
     * @return
     */
    private void updateSendSuccess (String kingInventoryId) {
        KingInventoryEntity kingInventory = new KingInventoryEntity ();
        kingInventory.setId ( kingInventoryId );
        kingInventory.setIsSend ( KingConstUtil.KING_DATA_IS_SEND_YES );
        kingInventory.setUpdateTime ( DateUtils.getNowDate () );
        kingInventory.setUpdateBy ( SecurityUtils.getLoginUser ().getUser ().getUserId () );
        boolean flag = kingInventoryService.updateById ( kingInventory );
        if ( ! flag ) {
            throw new CustomException ( "修改推送状态失败！" );
        }
    }


    /**
     * 金蝶-采购入库单保存
     * @param kingInventory
     * @param client
     */
    public void save (KingInventoryEntity kingInventory, K3CloudApi client) {
        try {
            String formId = KingConstUtil.STK_InStock;
            KingBaseSingleRequest singleRequest = new KingBaseSingleRequest ();
            KingInventoryBo kingInventoryBo = this.assembleInventory ( kingInventory );
            singleRequest.setModel ( kingInventoryBo );
            //调用接口
            String resultJson = client.save ( formId, JSONObject.toJSONString ( singleRequest ) );
            //用于记录结果
            Gson gson = new Gson ();
            //对返回结果进行解析和校验
            RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if ( baseResponse.getIsSuccess () ) {
                log.info ( "采购入库单推送成功: {}", gson.toJson ( repoRet.getResult () ) );
            } else {
                log.error ( "采购入库单推送失败: " + gson.toJson ( repoRet.getResult ().getResponseStatus () ) );
            }
        } catch ( Exception e ) {
            e.printStackTrace ();
        }
    }


    /**
     * 金蝶-采购入库单提交
     * @param docCode
     * @param client
     */
    public void submit (String docCode, K3CloudApi client) {
        try {
            OrderSubmitBo submitBo = new OrderSubmitBo ();
            List<String> numbers = new ArrayList<> ();
            numbers.add ( docCode );
            submitBo.setNumbers ( numbers );
            String formId = KingConstUtil.STK_InStock;
            String resultJson = client.submit ( formId, JSON.toJSONString ( submitBo ) );
            Gson gson = new Gson ();
            RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if ( baseResponse.getIsSuccess () ) {
                log.info ( "采购入库单提交成功: {}", gson.toJson ( repoRet.getResult () ) );
            } else {
                log.error ( "采购入库单提交失败: {}", gson.toJson ( repoRet.getResult ().getResponseStatus () ) );
            }
        } catch ( Exception e ) {
            e.printStackTrace ();
        }
    }

    /**
     * 金蝶审核方法
     * @param docCode
     * @param client
     */
    public void audit (String docCode, K3CloudApi client) {
        try {
            OrderAuditBo auditBo = new OrderAuditBo ();
            List<String> numbers = new ArrayList<> ();
            numbers.add ( docCode );
            auditBo.setNumbers ( numbers );
            String formId = KingConstUtil.STK_InStock;
            String resultJson = client.audit ( formId, JSON.toJSONString ( auditBo ) );
            Gson gson = new Gson ();
            RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if ( baseResponse.getIsSuccess () ) {
                log.info ( "采购入库单审核成功:{}", gson.toJson ( repoRet.getResult () ) );
            } else {
                log.error ( "采购入库单审核失败:{}", gson.toJson ( repoRet.getResult ().getResponseStatus () ) );
            }
        } catch ( Exception e ) {
            e.printStackTrace ();
        }
    }


    /**
     * 组装采购入库单推送金蝶对象
     * @param kingInventory
     * @return
     */
    private KingInventoryBo assembleInventory (KingInventoryEntity kingInventory) {
        KingInventoryBo inventoryBo = new KingInventoryBo ();
        //单据类型
        FBillTypeIDBo FBillTypeID = new FBillTypeIDBo ().setFNUMBER ( kingInventory.getDocType () );
        inventoryBo.setFBillTypeID ( FBillTypeID );
        //业务类型
        inventoryBo.setFBusinessType ( kingInventory.getDocBusinessType () );
        //单据编号
        inventoryBo.setFBillNo ( kingInventory.getDocCode () );
        //入库日期
        inventoryBo.setFDate ( dateFormat.format ( kingInventory.getInventoryTime () ) );
        //收料组织 kingInventory.getReceivingOrg()
        BaseChildBo FStockOrgId = new BaseChildBo ().setFNumber ( KingConstUtil.DEFAULT_ORG );
        inventoryBo.setFStockOrgId ( FStockOrgId );
        //收料部门
        BaseChildBo FStockDeptId = new BaseChildBo ().setFNumber ( kingInventory.getReceivingDept () );
        inventoryBo.setFStockDeptId ( FStockDeptId );
        //库存组
        BaseChildBo FStockerGroupId = new BaseChildBo ().setFNumber ( kingInventory.getInventoryGroup () );
        inventoryBo.setFStockerGroupId ( FStockerGroupId );
        //仓管员
        BaseChildBo FStockerId = new BaseChildBo ().setFNumber ( kingInventory.getManagementBy () );
        inventoryBo.setFStockerId ( FStockerId );
        //需求组织 kingInventory.getRequireDept()
        BaseChildBo FDemandOrgId = new BaseChildBo ().setFNumber ( KingConstUtil.DEFAULT_ORG );
        inventoryBo.setFDemandOrgId ( FDemandOrgId );
        //对应组织
        BaseChildBo FCorrespondOrgId = new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        //采购组织 kingInventory.getPurchaseOrg()
        BaseChildBo FPurchaseOrgId = new BaseChildBo ().setFNumber ( KingConstUtil.DEFAULT_ORG );
        inventoryBo.setFPurchaseOrgId ( FPurchaseOrgId );
        //采购部门
        BaseChildBo FPurchaseDeptId = new BaseChildBo ().setFNumber ( kingInventory.getPurchaseDept () );
        inventoryBo.setFPurchaseDeptId ( FPurchaseDeptId );
        //采购组
        BaseChildBo FPurchaserGroupId = new BaseChildBo ().setFNumber ( kingInventory.getPurchaseGroup () );
        inventoryBo.setFPurchaserGroupId ( FPurchaserGroupId );
        //采购员
        BaseChildBo FPurchaserId = new BaseChildBo ().setFNumber ( kingInventory.getPurchaseBy () );
        inventoryBo.setFPurchaserId ( FPurchaserId );
        //供应商 kingInventory.getSupplierCode()
        BaseChildBo FSupplierId = new BaseChildBo ().setFNumber ( "001" );
        inventoryBo.setFSupplierId ( FSupplierId );
        //供货方
        BaseChildBo FSupplyId = new BaseChildBo ().setFNumber ( kingInventory.getProviderCode () );
        inventoryBo.setFSupplyId ( FSupplyId );
        //供货方地址
        inventoryBo.setFSupplyAddress ( kingInventory.getProviderAddress () );
        //结算方
        BaseChildBo FSettleId = new BaseChildBo ().setFNumber ( kingInventory.getBalanceCode () );
        inventoryBo.setFSettleId ( FSettleId );
        //收款方
        BaseChildBo FChargeId = new BaseChildBo ().setFNumber ( kingInventory.getReceiveCode () );
        inventoryBo.setFChargeId ( FChargeId );
        //货主类型
        inventoryBo.setFOwnerTypeIdHead ( kingInventory.getCargoOwnerType () );
        //货主
        BaseChildBo FOwnerIdHead = new BaseChildBo ().setFNumber ( kingInventory.getCargoOwner () );
        inventoryBo.setFOwnerIdHead ( FOwnerIdHead );
        //确认人
        FConfirmerIdBo FConfirmerId = new FConfirmerIdBo ().setFUserID ( kingInventory.getConfirmName () );
        inventoryBo.setFConfirmerId ( FConfirmerId );
        //确认日期
        if ( Objects.nonNull ( kingInventory.getConfirmTime () ) ) {
            inventoryBo.setFConfirmDate ( dateFormat.format ( kingInventory.getConfirmTime () ) );
        }
        //供货方联系人
        FProviderContactIdBo FProviderContactID = new FProviderContactIdBo ().setFCONTACTNUMBER ( kingInventory.getProviderContacts () );
        inventoryBo.setFProviderContactID ( FProviderContactID );
        //邮箱
        inventoryBo.setFSupplyEMail ( kingInventory.getEmail () );

        /*** 采购入库单财务信息 ***/
        FInStockFinBo FInStockFin = new FInStockFinBo ();
        //明细信息结算组织 kingInventory.getSettlementOrg()
        BaseChildBo FSettleOrgId = new BaseChildBo ().setFNumber ( KingConstUtil.DEFAULT_ORG );
        FInStockFin.setFSettleOrgId ( FSettleOrgId );
        //明细信息结算方式
        BaseChildBo FSettleTypeId = new BaseChildBo ().setFNumber ( kingInventory.getSettlementMethod () );
        FInStockFin.setFSettleTypeId ( FSettleTypeId );
        //明细信息付款条件
        BaseChildBo FPayConditionId = new BaseChildBo ().setFNumber ( kingInventory.getTermOfPayment () );
        FInStockFin.setFPayConditionId ( FPayConditionId );
        //明细信息结算币别
        BaseChildBo FSettleCurrId = new BaseChildBo ().setFNumber ( kingInventory.getSettlementCurrency () );
        FInStockFin.setFSettleCurrId ( FSettleCurrId );
        //含税
        FInStockFin.setFIsIncludedTax ( kingInventory.getIsTax () );
        //定价时点
        FInStockFin.setFPriceTimePoint ( kingInventory.getPricingTimePoint () );
        //价目表
        BaseChildBo FPriceListId = new BaseChildBo ().setFNumber ( kingInventory.getPriceInfoCode () );
        FInStockFin.setFPriceListId ( FPriceListId );
        //折扣表
        BaseChildBo FDiscountListId = new BaseChildBo ().setFNumber ( kingInventory.getDiscountInfoCode () );
        FInStockFin.setFDiscountListId ( FDiscountListId );
        //本位币
        BaseChildBo FLocalCurrId = new BaseChildBo ().setFNumber ( kingInventory.getBaseCurrency () );
        FInStockFin.setFLocalCurrId ( FLocalCurrId );
        //汇率类型
        BaseChildBo FExchangeTypeId = new BaseChildBo ().setFNumber ( kingInventory.getExchangeRateType () );
        FInStockFin.setFExchangeTypeId ( FExchangeTypeId );
        //汇率
        FInStockFin.setFExchangeRate ( kingInventory.getExchangeRate () );
        //价外税
        FInStockFin.setFISPRICEEXCLUDETAX ( kingInventory.getIsExtraPriceTax () );
        //整单折扣额
        FInStockFin.setFAllDisCount ( kingInventory.getWholeDiscountAmount () );
        inventoryBo.setFInStockFin ( FInStockFin );

        /*** 采购入库单物料明细信息 ***/
        List<FInStockEntryBo> FInStockEntry = new ArrayList<> ();
        if ( ! CollectionUtils.isEmpty ( kingInventory.getMaterialLists () ) ) {
            List<KingInventoryMaterialEntity> materialLists = kingInventory.getMaterialLists ();
            for ( KingInventoryMaterialEntity inventoryMaterial : materialLists ) {
                FInStockEntryBo fInStockEntryBo = new FInStockEntryBo ();
                //入库类型
                fInStockEntryBo.setFWWInType ( inventoryMaterial.getInventoryType () );
                //物料编码
                BaseChildBo FMaterialId = new BaseChildBo ().setFNumber ( inventoryMaterial.getMaterialCode () );
                fInStockEntryBo.setFMaterialId ( FMaterialId );
                //库存单位
                BaseChildBo FUnitID = new BaseChildBo ().setFNumber ( inventoryMaterial.getInventoryUnit () );
                fInStockEntryBo.setFUnitID ( FUnitID );
                //物料说明
                fInStockEntryBo.setFMaterialDesc ( inventoryMaterial.getMaterialDesc () );
                //实收数量
                fInStockEntryBo.setFRealQty ( Integer.parseInt ( inventoryMaterial.getReceiptsNum () ) );
                //计价单位
                BaseChildBo FPriceUnitID = new BaseChildBo ().setFNumber ( inventoryMaterial.getPricingUnit () );
                fInStockEntryBo.setFPriceUnitID ( FPriceUnitID );
                //单价
                fInStockEntryBo.setFPrice ( inventoryMaterial.getPrice () );
                //含税单价
                fInStockEntryBo.setFTaxPrice ( inventoryMaterial.getContainsTaxPrice () );
                //税率
                fInStockEntryBo.setFEntryTaxRate ( inventoryMaterial.getTaxRate () );
                /*** 采购入库单物料明细分录信息 ***/
                KingInventoryMaterialDetailEntity inventoryMaterialDetail = inventoryMaterial.getMaterialDetail ();
                Optional.ofNullable ( inventoryMaterialDetail ).ifPresent ( materialDetail -> {
                    //拆单数量（计价）
                    fInStockEntryBo.setFDisPriceQty ( Integer.parseInt ( materialDetail.getPricingNum () ) );
                    //计划跟踪号
                    fInStockEntryBo.setFMtoNo ( materialDetail.getPlanTrackingCode () );
                    //生产日期
                    fInStockEntryBo.setFProduceDate ( dateFormat.format ( materialDetail.getManufactureTime () ) );
                    //辅单位
                    BaseChildBo FExtAuxUnitId = new BaseChildBo ().setFNumber ( materialDetail.getAuxiliaryUnit () );
                    fInStockEntryBo.setFExtAuxUnitId ( FExtAuxUnitId );
                    //实收数量
                    fInStockEntryBo.setFExtAuxUnitQty ( Integer.parseInt ( materialDetail.getReceivedNum () ) );
                    //计价基本数量
                    fInStockEntryBo.setFPriceBaseQty ( Integer.parseInt ( materialDetail.getPricingNum () ) );
                    //定价单位
                    BaseChildBo FSetPriceUnitID = new BaseChildBo ().setFNumber ( materialDetail.getPricingUnit () );
                    fInStockEntryBo.setFSetPriceUnitID ( FSetPriceUnitID );
                    //成本价
                    //bom版本
                    BaseChildBo FBOMId = new BaseChildBo ().setFNumber ( materialDetail.getBomVer () );
                    fInStockEntryBo.setFBOMId ( FBOMId );
                    //供应商批号
                    fInStockEntryBo.setFSupplierLot ( materialDetail.getSupplierBatchNum () );
                    //有效期至
                    fInStockEntryBo.setFExpiryDate ( dateFormat.format ( materialDetail.getValidTo () ) );
                    //数量(库存辅单位)
                    fInStockEntryBo.setFAuxUnitQty ( materialDetail.getReceivedNum () );
                    //单价折扣
                    fInStockEntryBo.setFPriceDiscount ( materialDetail.getPriceDiscount () );
                } );
                //批号（需要启用批号管理才可以录入）
//                BaseChildBo FLot = new BaseChildBo().setFNumber(inventoryMaterial.getBatchNum());
//                fInStockEntryBo.setFLot(FLot);
                //仓库 inventoryMaterial.getWarehouseCode()
                BaseChildBo FStockId = new BaseChildBo ().setFNumber ( "CK001" );
                fInStockEntryBo.setFStockId ( FStockId );
                //仓位
//                FStockLocIdBo FStockLocId = new FStockLocIdBo();
                //库存状态 inventoryMaterial.getInventoryStatus()
                BaseChildBo FStockStatusId = new BaseChildBo ().setFNumber ( "KCZT01_SYS" );
                fInStockEntryBo.setFStockStatusId ( FStockStatusId );
                //是否赠品
                fInStockEntryBo.setFGiveAway ( inventoryMaterial.getIsGiveaway () );
                //备注
                fInStockEntryBo.setFNote ( inventoryMaterial.getRemark () );
                //货主类型
                fInStockEntryBo.setFOWNERTYPEID ( kingInventory.getCargoOwnerType () );
                //采购单位
                BaseChildBo FRemainInStockUnitId = new BaseChildBo ().setFNumber ( inventoryMaterial.getPurchaseUnit () );
                fInStockEntryBo.setFRemainInStockUnitId ( FRemainInStockUnitId );
                //采购数量
                fInStockEntryBo.setFRemainInStockQty ( inventoryMaterial.getPurchaseNum () );
                //采购基本数量
                fInStockEntryBo.setFRemainInStockBaseQty ( inventoryMaterial.getPurchaseNum () );
                //货主
                BaseChildBo FOWNERID = new BaseChildBo ().setFNumber ( kingInventory.getCargoOwner () );
                fInStockEntryBo.setFOWNERID ( FOWNERID );
                //源单类型
                fInStockEntryBo.setFSRCBILLTYPEID ( inventoryMaterial.getSourceType () );
                //源单编号
                fInStockEntryBo.setFSRCBillNo ( inventoryMaterial.getRelationCode () );
                //不良品折让金额
                fInStockEntryBo.setFRejectsDiscountAmount ( inventoryMaterial.getDefectiveDiscountAmount () );

                FInStockEntry.add ( fInStockEntryBo );
            }
        }
        inventoryBo.setFInStockEntry ( FInStockEntry );
        return inventoryBo;
    }


}
